home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Linux Cubed Series 8: LINUX Games
/
Linux Cubed Series 8 - LINUX Games.iso
/
games
/
muds
/
pennmush.000
/
pennmush-1.50-p8-linux.tar
/
pennmush
/
cque.c
< prev
next >
Wrap
C/C++ Source or Header
|
1993-02-16
|
18KB
|
771 lines
/* cque.c */
#include <ctype.h>
#include <fcntl.h>
#include <string.h>
#ifdef XENIX
#include <sys/signal.h>
#else
#include <signal.h>
#endif /* xenix */
#include "config.h"
#include "db.h"
#include "interface.h"
#include "match.h"
#include "externs.h"
#ifdef MEM_CHECK
#include "mem_check.h"
#endif
extern char ccom[];
extern dbref cplr;
extern int atoi();
typedef struct bque BQUE;
struct bque {
BQUE *next;
dbref player; /* player who will do command */
dbref cause; /* player causing command (for %N) */
dbref sem; /* semaphore object to block on */
int left; /* seconds left until execution */
char *env[10]; /* environment, from wild match */
char *comm; /* command to be executed */
};
static BQUE *qfirst = NULL, *qlast = NULL, *qwait = NULL;
static BQUE *qlfirst = NULL, *qllast = NULL;
static BQUE *qsemfirst = NULL, *qsemlast = NULL;
void parse_que(player, command, cause)
dbref player;
char *command;
dbref cause; /* cause is needed to determine priority */
{
char buff[BUFFER_LEN], *s, *r;
void big_que();
s = buff;
strcpy(buff, command);
while ((r = parse_to(&s, ';', 0)) != NULL)
big_que(player, r, cause);
}
static int add_to_generic(player, am, key)
dbref player;
int am;
int key; /* 0 for queue, 1 for semaphore */
{
int num = 0;
ATTR *a;
const char *atrname;
char buff[MAX_COMMAND_LEN];
if (key == 0) {
atrname = "QUEUE";
player = Owner(player);
} else {
atrname = "SEMAPHORE";
}
a = atr_get_noparent(player, atrname); /* don't get from the parent! */
if (a)
num = atoi(uncompress(a->value));
num += am;
if (num)
sprintf(buff, "%d", num);
else
*buff = '\0';
(void) atr_add(player, atrname, buff, GOD, NOTHING);
return (num);
}
static int add_to(player, am)
dbref player;
int am;
{
return (add_to_generic(player, am, 0));
}
static int add_to_sem(player, am)
dbref player;
int am;
{
return (add_to_generic(player, am, 1));
}
static int queue_limit(player)
dbref player;
{
/* returns 1 if player has exceeded his queue limit */
if (HugeQueue(player)) {
if (add_to(player, 1) > (10 * QUEUE_QUOTA))
return 1;
else
return 0;
} else {
if (add_to(player, 1) > QUEUE_QUOTA)
return 1;
else
return 0;
}
return 0; /* NOTREACHED */
}
void free_qentry(point)
BQUE *point;
{
int a;
for (a = 0; a < 10; a++)
if (point->env[a]) {
free((char *)point->env[a]);
#ifdef MEM_CHECK
del_check("bqueue_env");
#endif
}
if (point->comm)
free((char *)point->comm);
free((char *)point);
#ifdef MEM_CHECK
del_check("bqueue_comm");
del_check("bqueue");
#endif
}
void big_que(player, command, cause)
dbref player;
char *command;
dbref cause;
{
int a;
BQUE *tmp;
if ((Typeof(player) != TYPE_PLAYER) && (Halted(player)))
return;
/* make sure player can afford to do it */
if (!payfor(player, QUEUE_COST + (((random() & QUEUE_LOSS) == 0) ? 1 : 0))) {
notify(Owner(player), "Not enough money to queue command.");
return;
}
if (queue_limit(player)) {
notify(Owner(player),
tprintf("Runaway object: %s(#%d). Commands halted.",
Name(player), player));
/* wipe out that object's queue and set it HALT */
do_halt(Owner(player), "", player);
Flags(player) |= HALT;
return;
}
tmp = (BQUE *) malloc (sizeof(BQUE));
strcpy((tmp->comm = (char *) malloc(strlen(command)+1)), command);
#ifdef MEM_CHECK
add_check("bqueue");
add_check("bqueue_comm");
#endif
tmp->player = player;
tmp->next = NULL;
tmp->left = 0;
tmp->cause = cause;
for (a = 0; a < 10; a++)
if (!wptr[a])
tmp->env[a] = NULL;
else {
strcpy((tmp->env[a] = (char *)malloc(strlen(wptr[a])+1)), wptr[a]);
#ifdef MEM_CHECK
add_check("bqueue_env");
#endif
}
if (Typeof(cause) == TYPE_PLAYER) {
if (qlast) {
qlast->next = tmp;
qlast = tmp;
} else
qlast = qfirst = tmp;
} else {
if (qllast) {
qllast->next = tmp;
qllast = tmp;
} else
qllast = qlfirst = tmp;
}
}
void wait_que(player, wait, command, cause, sem)
dbref player;
int wait;
char *command;
dbref cause;
dbref sem;
{
BQUE *tmp;
int a;
/* make sure player can afford to do it */
if (!payfor(player, QUEUE_COST + (((random() & QUEUE_LOSS) == 0) ? 1 : 0))) {
notify(player, "Not enough money to queue command.");
return;
}
tmp = (BQUE *)malloc(sizeof(BQUE));
strcpy((tmp->comm = (char *)malloc(strlen(command)+1)), command);
#ifdef MEM_CHECK
add_check("bqueue");
add_check("bqueue_comm");
#endif
tmp->player = player;
tmp->cause = cause;
tmp->sem = sem;
tmp->left = wait;
for (a = 0; a < 10; a++) {
if (!wptr[a])
tmp->env[a] = NULL;
else {
strcpy((tmp->env[a] = (char *)malloc(strlen(wptr[a])+1)), wptr[a]);
#ifdef MEM_CHECK
add_check("bqueue_env");
#endif
}
}
if (sem == NOTHING) {
/* No semaphore, put on normal wait queue */
tmp->next = qwait;
qwait = tmp;
} else {
/* Put it on the semaphore queue */
tmp->next = NULL;
if (qsemlast != NULL)
qsemlast->next = tmp;
else
qsemfirst = tmp;
qsemlast = tmp;
}
}
void do_second()
{
/* call every second to check for wait queue commands */
BQUE *trail = NULL, *point, *next;
int a;
/* move contents of low priority queue onto end of normal one
* this helps to keep objects from getting out of control since
* its effects on other objects happen only after one second
* this should allow @halt to be typed before getting blown away
* by scrolling text.
*/
if (qlfirst) {
if (qlast)
qlast->next = qlfirst;
else
qfirst = qlfirst;
qlast = qllast;
qllast = qlfirst = NULL;
}
/* check regular wait queue */
for (point = qwait, trail = NULL; point; point = next) {
/*
* Note: this would be 0 except the command is being put in the low
* priority queue to be done in one second anyways
*/
if (point->left-- <= 1) {
if (trail != NULL)
trail->next = next = point->next;
else
qwait = next = point->next;
giveto(point->player, QUEUE_COST);
for (a = 0; a < 10; a++) {
wptr[a] = point->env[a];
}
parse_que(point->player, point->comm, point->cause);
free_qentry(point);
} else
next = (trail = point)->next;
}
/* check for semaphore timeouts */
for (point = qsemfirst, trail = NULL; point; point = next) {
if (point->left < 0) {
next = (trail = point)->next;
continue; /* skip non-timed waits */
}
if (point->left-- <= 1) {
if (trail != NULL)
trail->next = next = point->next;
else
qsemfirst = next = point->next;
if (point == qsemlast)
qsemlast = trail;
giveto(point->player, QUEUE_COST);
add_to_sem(point->sem, -1);
point->sem = NOTHING;
for (a = 0; a < 10; a++) {
wptr[a] = point->env[a];
}
parse_que(point->player, point->comm, point->cause);
free_qentry(point);
} else
next = (trail = point)->next;
}
}
int test_top()
{
return (qfirst ? 1 : 0);
}
/* execute one command off the top of the queue */
int do_top()
{
int a;
int i = 0;
BQUE *tmp;
dbref player;
char tbuf1[BUFFER_LEN], tbuf2[BUFFER_LEN];
char tbuf3[BUFFER_LEN], *s;
if (!qfirst)
return (0);
if (qfirst->player && !Going(qfirst->player)) {
giveto(qfirst->player, QUEUE_COST);
cplr = qfirst->player;
strcpy(ccom, qfirst->comm);
add_to(player = qfirst->player, -1);
qfirst->player = 0;
if ((Typeof(player) == TYPE_PLAYER) || !Halted(player)) {
for (a = 0; a < 10; a++) {
wptr[a] = qfirst->env[a];
}
strcpy(tbuf2, uncompress(qfirst->comm));
tbuf3[0] = '\0';
for (s = tbuf2; *s; tbuf3[i++] = toupper(*s++)) ;
tbuf3[i++] = '\0';
strcpy(tbuf1, tbuf2);
process_command(player, tbuf1, qfirst->cause, 0);
}
}
tmp = qfirst->next;
free_qentry(qfirst);
if (!(qfirst = tmp))
qlast = NULL;
return (1);
}
int nfy_que(sem, key, count)
dbref sem;
int key; /* 0 is normal, 1 is all, 2 is drain */
int count;
{
BQUE *point, *trail, *next;
int num;
ATTR *a;
int x;
a = atr_get_noparent(sem, "SEMAPHORE");
if (a)
num = atoi(uncompress(a->value));
else
num = 0;
if (num > 0) {
num = 0;
for (point = qsemfirst, trail = NULL; point; point = next) {
if (point->sem == sem) {
num++;
if (trail)
trail->next = next = point->next;
else
qsemfirst = next = point->next;
if (point == qsemlast)
qsemlast = trail;
/* run or discard the command */
giveto(point->player, QUEUE_COST);
for (x = 0; x < 10; x++)
wptr[x] = point->env[x];
if (key != 2)
parse_que(point->player, point->comm, point->cause);
else
free_qentry(point);
} else {
next = (trail = point)->next;
}
/* if we've notified enough, exit. Note that we don't have to check
* for the case of @notify/all, since we don't break out of this
* loop "manually" unless the key is standard @notify.
*/
if ((key == 0) && (num >= count))
next = NULL;
}
} else {
num = 0;
}
/* update the semaphore waiter's count */
if (key == 0)
add_to_sem(sem, -count);
else
atr_add(sem, "SEMAPHORE", "", GOD, NOTHING);
return num;
}
void do_notify(player, cause, key, what, count)
dbref player;
dbref cause;
int key; /* 0 is normal, 1 is all, 2 is drain */
char *what;
char *count;
{
dbref thing;
int i;
/* find it */
init_match(player, what, NOTYPE);
match_everything();
if ((thing = noisy_match_result()) == NOTHING)
return;
/* must control something or have it link_ok in order to use it as
* as a semaphore.
*/
if (!controls(player, thing) && !LinkOk(thing)) {
notify(player, "Permission denied.");
return;
}
/* find how many times to notify */
if (count && *count)
i = atoi(count);
else
i = 1;
if (i > 0)
nfy_que(thing, key, i);
if (key != 2) {
quiet_notify(player, "Notified.");
} else {
quiet_notify(player, "Drained.");
}
}
void do_wait(player, cause, arg1, cmd)
dbref player;
dbref cause;
char *arg1;
char *cmd;
{
dbref thing;
char *tcount;
int waitfor, num;
ATTR *a;
char *arg2;
arg2 = strip_braces(cmd);
if (is_number(arg1)) {
/* normal wait */
wait_que(player, atoi(arg1), arg2, cause, NOTHING);
free(arg2);
return;
}
/* semaphore wait with optional timeout */
/* find the thing to wait on */
tcount = (char *) index(arg1, '/');
if (tcount)
*tcount++ = '\0';
init_match(player, arg1, NOTYPE);
match_everything();
if ((thing = noisy_match_result()) == NOTHING) {
free(arg2);
return;
}
if (!controls(player, thing) && !LinkOk(thing)) {
notify(player, "Permission denied.");
free(arg2);
return;
}
/* get timeout, default of -1 */
if (tcount && *tcount)
waitfor = atol(tcount);
else
waitfor = -1;
add_to_sem(thing, 1);
a = atr_get_noparent(thing, "SEMAPHORE");
if (a)
num = atoi(uncompress(a->value));
else
num = 0;
if (num <= 0) {
thing = NOTHING;
waitfor = -1; /* just in case there was a timeout given */
}
wait_que(player, waitfor, arg2, cause, thing);
free(arg2);
}
void do_queue(player, what)
dbref player;
const char *what;
{
/* tell player what commands they have pending in the queue (@ps) */
BQUE *tmp;
dbref victim = NOTHING;
int everything = 0;
int quick = 0;
int pq = 0, oq = 0, wq = 0, sq = 0;
int tpq = 0, toq = 0, twq = 0, tsq = 0;
if (!strcasecmp(what, "count")) {
victim = player;
everything = 1;
quick = 1;
}
else if (LookQueue(player)) {
if(!what || !*what)
victim = player;
else
if(!strcasecmp(what, "all")) { /* do the whole thing */
victim = player;
everything = 1;
} else {
init_match(player, what, TYPE_PLAYER);
match_player();
match_absolute();
match_me();
victim = match_result();
}
} else {
victim = player;
}
switch(victim) {
case NOTHING:
notify(player, "I couldn't find that player.");
break;
case AMBIGUOUS:
notify(player, "I don't know who you mean!");
break;
default:
if(everything == 1)
notify(player, "Queue for : all");
else
notify(player, tprintf("Queue for : %s", db[victim].name));
if (!quick) notify(player,"Player Queue:");
for (tmp = qfirst; tmp; tmp = tmp->next) {
tpq++;
if ((Owner(tmp->player) == Owner(victim)) || (everything)) {
pq++;
if (!quick)
notify(player, tprintf("%s:%s", unparse_object(player, tmp->player),
tmp->comm));
}
}
if (!quick) notify(player,"Object Queue:");
for (tmp = qlfirst; tmp; tmp = tmp->next) {
toq++;
if ((Owner(tmp->player) == Owner(victim)) || (everything)) {
oq++;
if (!quick)
notify(player, tprintf("%s:%s", unparse_object(player, tmp->player),
tmp->comm));
}
}
if (!quick) notify(player, "Wait Queue:");
for (tmp = qwait; tmp; tmp = tmp->next) {
twq++;
if ((Owner(tmp->player) == Owner(victim)) || (everything)) {
wq++;
if (!quick)
notify(player, tprintf("[%d]%s:%s", tmp->left,
unparse_object(player, tmp->player),
tmp->comm));
}
}
if (!quick) notify(player, "Semaphore Queue:");
for (tmp = qsemfirst; tmp; tmp = tmp->next) {
tsq++;
if ((Owner(tmp->player) == Owner(victim)) || (everything)) {
sq++;
if (!quick) {
if (tmp->left != -1)
notify(player, tprintf("[#%d/%d]%s:%s", tmp->sem, tmp->left,
unparse_object(player, tmp->player),
tmp->comm));
else
notify(player, tprintf("[#%d]%s:%s", tmp->sem,
unparse_object(player, tmp->player),
tmp->comm));
}
}
}
notify(player,"------------ Queue Done ------------");
notify(player,
tprintf(
"Totals: Player...%d/%d Object...%d/%d Wait...%d/%d Semaphore...%d/%d",
pq, tpq, oq, toq, wq, twq, sq, tsq));
}
}
void do_halt(owner, ncom, victim)
dbref owner;
char *ncom;
dbref victim;
{
BQUE *tmp, *trail = NULL, *point, *next;
int num = 0;
dbref player;
if (victim == NOTHING)
player = owner;
else
player = victim;
quiet_notify(Owner(player), "Halted.");
for (tmp = qfirst; tmp; tmp = tmp->next)
if (((tmp->player == player) || (Owner(tmp->player) == player))
&& !Immortal(tmp->player)) {
num--;
giveto(player, QUEUE_COST);
tmp->player = 0;
}
for (tmp = qlfirst; tmp; tmp = tmp->next)
if (((tmp->player == player) || (Owner(tmp->player) == player))
&& !Immortal(tmp->player)) {
num--;
giveto(player, QUEUE_COST);
tmp->player = 0;
}
/* remove wait q stuff */
for (point = qwait; point; point = next) {
if (((point->player == player) || (Owner(point->player) == player))
&& !Immortal(point->player)) {
giveto(player, QUEUE_COST);
if (trail)
trail->next = next = point->next;
else
qwait = next = point->next;
free_qentry(point);
} else
next = (trail = point)->next;
}
/* clear semaphore queue */
for (point = qsemfirst, trail = NULL; point; point = next) {
if (((point->player == player) || (Owner(point->player) == player)) &&
!Immortal(point->player)) {
giveto(player, QUEUE_COST);
if (trail)
trail->next = next = point->next;
else
qsemfirst = next = point->next;
if (point == qsemlast)
qsemlast = trail;
add_to_sem(point->sem, -1);
free_qentry(point);
} else
next = (trail = point)->next;
}
if (Owner(player) == player)
(void) atr_add(player, "QUEUE", "", GOD, NOTHING);
else
add_to(player, num);
if (*ncom)
parse_que(player, ncom, player);
}
void do_halt1(player, arg1, arg2)
dbref player;
const char *arg1;
const char *arg2;
{
dbref victim;
if (*arg1 == '\0')
do_halt(player, "", player);
else {
init_match(player, arg1, NOTYPE);
match_neighbor();
match_possession();
match_me();
match_absolute();
match_player();
if ((victim = noisy_match_result()) == NOTHING)
return;
if (!Owns(player, victim) && !HaltAny(player)) {
notify(player, "Permission denied.");
return;
}
/* if not player and no new command provided, set it HALT */
if ((Typeof(victim) != TYPE_PLAYER) && (*arg2 == '\0')) {
Flags(victim) |= HALT;
}
if (Owner(victim) != player) {
if (Typeof(victim) == TYPE_PLAYER) {
notify(player, tprintf("All objects for %s have been halted.",
Name(victim)));
notify(victim, tprintf("All of your objects have been halted by %s.",
Name(player)));
} else {
notify(player, tprintf("Halted: %s's %s(#%d)",
Name(Owner(victim)), Name(victim),
victim));
notify (Owner(victim),
tprintf("Halted: %s(#%d), by %s", Name(victim),
victim, Name(player)));
}
} else {
if (victim == player)
notify(player, "All of your objects have been halted.");
else
notify(player, tprintf("Halted: %s(#%d)", Name(victim), victim));
}
do_halt(player, arg2, victim);
}
}
void do_allhalt(player)
dbref player;
{
dbref victim;
if (!HaltAny(player)) {
notify(player, "You do not have the power to bring the world to a halt.");
return;
}
for(victim = 0;victim <db_top; victim++) {
if(Typeof(victim) == TYPE_PLAYER) {
notify(victim,tprintf("Your objects have been globally halted by %s",
Name(player)));
do_halt(victim, "", victim);
}
}
}